package tianrun.ziguan.api.calculate.config.service.common.edit;

import com.alibaba.fastjson.PropertyNamingStrategy;
import com.google.common.collect.Maps;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import tianrun.ziguan.api.calculate.config.dto.request.common.DeleteBody;
import tianrun.ziguan.api.calculate.config.dto.request.common.add.edit.AddOrEditBody;
import tianrun.ziguan.api.calculate.config.dto.request.common.add.edit.SaveBody;
import tianrun.ziguan.api.calculate.config.entity.ge.TGeTableConfig;
import tianrun.ziguan.api.calculate.config.service.ge.TGeTableConfigService;
import tianrun.ziguan.api.common.util.BeanUtil;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public abstract class AbstractDealService implements DealService {

    private final TGeTableConfigService tableConfigService;

    protected AbstractDealService(TGeTableConfigService tableConfigService) {
        this.tableConfigService = tableConfigService;
    }

    @Override
    public abstract void before(SaveBody body);

    @Override
    public SaveBody handler(AddOrEditBody body) {
        Map<String, TGeTableConfig> configMap = tableConfigService.mapByTableName(body.getTableName());
        Assert.notEmpty(configMap, body.getTableName() + "无相关配置！");

        Set<String> keys = configMap.values().stream().filter(TGeTableConfig::getPrimaryKey).map(TGeTableConfig::getColumnName).collect(Collectors.toSet());
        Map<String, Object> data = body.getData().entrySet().stream().filter(entry -> configMap.containsKey(entry.getKey())).collect(HashMap::new, (newMap, item) -> {
            TGeTableConfig config = configMap.get(item.getKey());
            Object value = item.getValue();
            Object o = config == null ? TGeTableConfig.Type.STRING.parseIn(value) : config.getType().parseIn(value);
            newMap.put(item.getKey(), o);
        }, HashMap::putAll);
        Map<String, Object> keymap = data.keySet().stream().filter(keys::contains).collect(Collectors.toMap(Function.identity(), data::get));
        data.keySet().removeIf(keymap::containsKey);

        SaveBody saveBody = new SaveBody();
        saveBody.setRawData(body.getData());
        saveBody.setTableName(body.getTableName());
        saveBody.setData(data);
        saveBody.keymap(keymap);
        return saveBody;
    }

    @Override
    public abstract String tableName();

    @Override
    public abstract void after(SaveBody body);

    @Override
    public abstract void delBefore(DeleteBody body);

    @Override
    public abstract void listAfter(List<Map<String, Object>> result);

    @Override
    public void delAfter(DeleteBody body) {

    }
    protected static HashMap<String, Object> getBeanMapBySnakeCase(Object bean) {
        HashMap<String, Object> map = Maps.newHashMap();
        BeanUtil.beanToMap(bean).forEach((s, o) -> {
            map.put(PropertyNamingStrategy.SnakeCase.translate(s),o);
        });
        return map;
    }
}
